package com.jh.fcsm.service.sys.impl;

import com.jh.fcsm.beans.sys.SysFileInfo;
import com.jh.fcsm.common.exception.ServiceException;
import com.jh.fcsm.dao.sys.SysFileInfoMapper;
import com.jh.fcsm.enums.FileSource;
import com.jh.fcsm.service.sys.FileService;
import com.jh.fcsm.util.io.FileUtil;
import com.jh.fcsm.util.security.UUIDUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Files;

public abstract class AbstractFileService implements FileService {
    public static final Logger logger = LoggerFactory.getLogger(AbstractFileService.class);

    protected abstract SysFileInfoMapper getFileDao();

    @Override
    public SysFileInfo upload(MultipartFile file) throws Exception {
        // 上传文件的信息
        SysFileInfo fileInfo = FileUtil.getFileInfo(file);
        // 先根据文件md5查询记录
        SysFileInfo oldFileInfo = getFileDao().selectByPrimaryKey(fileInfo.getId());

        if (oldFileInfo != null) {// 如果已存在文件，避免重复上传同一个文件
            return oldFileInfo;
        }
        // 上传文件的后缀名
        if (!fileInfo.getName().contains(".")) {
            throw new IllegalArgumentException("缺少后缀名");
        }
        uploadFile(file, fileInfo);
        fileInfo.setSource(fileSource().name());// 设置文件来源
        fileInfo.setId(UUIDUtils.getUUID());
        String md5 = FileUtil.fileMd5(file.getInputStream());
        fileInfo.setMd5(md5);
        getFileDao().insertSelective(fileInfo);// 将文件信息保存到数据库
        logger.info("上传文件：{}", fileInfo);
        return fileInfo;
    }

    /**
     * 重载上传方法
     *
     * @author szx
     */
    @Override
    public SysFileInfo upload(MultipartFile file, SysFileInfo sysfileInfo) throws Exception {

        String s1 = file.getOriginalFilename();
        String[] px = "jpg,pdf,rar,zip,7z,png,gif,bmp,tif,jpeg,doc,docx,xls,xlsx,3gp,mov,mp4,m4v,mpg,mpeg,avi,rm,rmvb,mov,wmv,asf,asx,dat,cebx".split(",");
        boolean pass = false;
        for (String p : px) {
            if (s1.endsWith("."+p)) {
                pass = true;
                break;
            }
        }
        if (!pass) {
            throw new ServiceException("不支持的文件类型");
        }
        if(!FileUtil.isFileType(file.getInputStream(),px)){
            throw new ServiceException("不支持的文件类型");
        }

        // 上传文件的信息
        SysFileInfo fileInfo = FileUtil.getFileInfo(file);
        // 先根据文件md5查询记录
        SysFileInfo oldFileInfo = getFileDao().selectByPrimaryKey(fileInfo.getId());
        if (oldFileInfo != null) {// 如果已存在文件，避免重复上传同一个文件
            return oldFileInfo;
        }
        // 上传文件的后缀名
        if (!fileInfo.getName().contains(".")) {
            throw new IllegalArgumentException("缺少后缀名");
        }
        fileInfo.setSource(fileSource().name());// 设置文件来源
        uploadFile(file, fileInfo);
        fileInfo.setId(UUIDUtils.getUUID());
        String md5 = FileUtil.fileMd5(file.getInputStream());
        fileInfo.setMd5(md5);
        getFileDao().insertSelective(fileInfo);// 将文件信息保存到数据库
        logger.info("上传文件：{}", fileInfo);
        return fileInfo;
    }
    /**
     * 重载上传方法
     *
     * @author szx
     */
    @Override
    public SysFileInfo upload(MultipartFile file, SysFileInfo sysfileInfo, String markPath) throws Exception {

        String s1 = file.getOriginalFilename();
        String[] px = "jpg,pdf,rar,zip,7z,png,gif,bmp,tif,jpeg,doc,docx,xls,xlsx,3gp,mov,mp4,m4v,mpg,mpeg,avi,rm,rmvb,mov,wmv,asf,asx,dat,cebx".split(",");
        boolean pass = false;
        for (String p : px) {
            if (s1.endsWith("."+p)) {
                pass = true;
                break;
            }
        }
        if (!pass) {
            throw new ServiceException("不支持的文件类型");
        }
        if(!FileUtil.isFileType(file.getInputStream(),px)){
            throw new ServiceException("不支持的文件类型");
        }

        // 上传文件的信息
        SysFileInfo fileInfo = FileUtil.getFileInfo(file);
        // 先根据文件md5查询记录
        SysFileInfo oldFileInfo = getFileDao().selectByPrimaryKey(fileInfo.getId());
        if (oldFileInfo != null) {// 如果已存在文件，避免重复上传同一个文件
            return oldFileInfo;
        }
        // 上传文件的后缀名
        if (!fileInfo.getName().contains(".")) {
            throw new IllegalArgumentException("缺少后缀名");
        }

        uploadFile(file, fileInfo, markPath);

        fileInfo.setSource(fileSource().name());// 设置文件来源
        fileInfo.setId(UUIDUtils.getUUID());
        String md5 = FileUtil.fileMd5(file.getInputStream());
        fileInfo.setMd5(md5);
        getFileDao().insertSelective(fileInfo);// 将文件信息保存到数据库
        logger.info("上传文件：{}", fileInfo);
        return fileInfo;
    }

    @Override
    public SysFileInfo upload(File file, SysFileInfo fileInfo) throws Exception {

        // 上传文件的后缀名
        FileUtil.getFileInfo(file, fileInfo);
        if (!fileInfo.getName().contains(".")) {
            throw new IllegalArgumentException("缺少后缀名");
        }

        uploadLocalFile(file, fileInfo);

        fileInfo.setSource(fileSource().name());// 设置文件来源
        fileInfo.setId(UUIDUtils.getUUID());
        try (InputStream inputStream = Files.newInputStream(file.toPath())) {
            String md5 = FileUtil.fileMd5(inputStream);
            fileInfo.setMd5(md5);
        }
        getFileDao().insertSelective(fileInfo);// 将文件信息保存到数据库

        logger.info("上传文件：{}", fileInfo);
        return fileInfo;
    }

    protected abstract SysFileInfo uploadLocalFile(File file, SysFileInfo fileInfo) throws Exception;

    /**
     * 文件来源
     *
     * @return
     */
    protected abstract FileSource fileSource();

    /**
     * 上传文件
     *
     * @param file
     * @param fileInfo
     */
    protected abstract void uploadFile(MultipartFile file, SysFileInfo fileInfo) throws Exception;

    /**
     * 上传配置文件
     *
     * @param file
     * @param fileInfo
     */
    protected abstract void uploadFile(MultipartFile file, SysFileInfo fileInfo, String markPath) throws Exception;

    @Override
    public void delete(SysFileInfo fileInfo) {
        deleteFile(fileInfo);
        getFileDao().deleteByPrimaryKey(fileInfo.getId());
        logger.info("删除文件：{}", fileInfo);
    }

    /**
     * 删除文件资源
     *
     * @param fileInfo
     * @return
     */
    protected abstract boolean deleteFile(SysFileInfo fileInfo);

}
